/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DataStructuresThreads;

import Sorting.Main;
import Sorting.ThreadAuxiliary;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.geometry.Sphere;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.*;
import javax.vecmath.Vector3f;

/**
 *
 * @author rafael
 */
public class VectorThread extends Thread {
    
    public VectorThread vectorThread = this;
    public static boolean isRunning = false;
    public static Vector3f elementPosition = new Vector3f(-0.2f, 0.0f, -0.2f);
    public static Vector3f view = new Vector3f(0.0f, 0.0f, 0.0f);
    public static Sorting.Number vector[];
    public static List<Sorting.Number> shadow;

    public VectorThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        execute();
    }

    private void execute() {

        try {

            Main.textPane.setText(Main.textoVectorAdd);
            callVectorButtons();
            Main.frame.setEnabled(false);

            BranchGroup bgroup = Main.vectorBranchGroup();
            Main.su.addBranchGraph(bgroup);

        } finally {
            Main.isRunning = false;
            Main.textPane.setText(Main.textoVectorAdd);
        }
    }

    private static void checkElementPosition(int index) {

        elementPosition.x = (index * 0.25f) - 0.4f;

    }

    public static void insertElement() {
        Main.textPane.setText(Main.textoVectorAdd);

        String indexString = "";
        int indexNumber = -1;

        while (indexNumber < 0 || indexNumber > 9) {
            indexString = JOptionPane.showInputDialog("Qual a posição do número adicionado? Capacidade atual: " + Main.vectorCapacity);

            if (indexString == null || indexString.equals("")) {
            } else {
                indexNumber = Integer.parseInt(indexString);
            }

        }

        Main.highlightsText("  se (indice < 0 || indice > tamanho_vetor) {", Main.textoVectorAdd);
        if (indexNumber < 0 || indexNumber > Main.vectorSize) {
            Main.highlightsText("    Erro: O índice não está nos limites do vetor!\n", Main.textoVectorAdd);
            JOptionPane.showMessageDialog(null, "O índice não está dentro dos limites do vetor atual.");
            Main.textPane.getStyledDocument().setCharacterAttributes(0, Main.textoVectorAdd.length(), Main.defaultText, true);

        } else {
            Main.highlightsText("  } senao {\n", Main.textoVectorAdd);

            Main.highlightsText("    se (tamanho_vetor == capacidade_vetor) {", Main.textoVectorAdd);
            if (Main.vectorSize == Main.vectorCapacity) {
                Main.highlightsText("      vetorTemp = vetor[tamanho_vetor];", Main.textoVectorAdd);
                
                //  --------------------DAQUI! ---------------------
                vector = new Sorting.Number[Main.vectorCapacity];
                shadow = new ArrayList<Sorting.Number>();
                
                for (int i = 0; i < Main.vectorCapacity; i++) {
                
                    BranchGroup bGroup = new BranchGroup();

                    Box box = new Box(Main.raio, Main.raio, Main.raio, Main.criarAppCustom());
                    box.setCapability(Box.ENABLE_APPEARANCE_MODIFY);
                    Transform3D tfBox = new Transform3D();
                    checkElementPosition(i);

                    tfBox.setTranslation(new Vector3f(elementPosition.x, -0.5f, -0.25f));
                    TransformGroup tgBox = new TransformGroup(tfBox);
                    tgBox.addChild(box);

                    shadow.add(new Sorting.Number(-1, tgBox));
                    
                    bGroup.addChild(tgBox);
                    Main.su.addBranchGraph(bGroup);
                
                }
                
                
                Sorting.Number number[] = new Sorting.Number[Main.vectorCapacity];

                Main.highlightsText("        para (int i = 0; i < tamanho_vetor; i++) {", Main.textoVectorAdd);
                for (int i = 0; i < Main.vectorCapacity; i++) {
                    
                    
                    Main.highlightsText("          vetorTemp[i] = vetor[i];", Main.textoVectorAdd);
                    number[i] = Main.vetorNumeros[i];
                    
                }
                
                for (int y = 0; y < Main.vectorCapacity; y++) {
                
                    BranchGroup bGroup = new BranchGroup();

                    Box box = new Box(Main.raio, Main.raio, Main.raio, Main.criarAppCustom());
                    box.setCapability(Box.ENABLE_APPEARANCE_MODIFY);
                    Transform3D tfBox = new Transform3D();
                    checkElementPosition(y);

                    tfBox.setTranslation(new Vector3f(elementPosition.x, -0.5f, elementPosition.z));
                    TransformGroup tgBox = new TransformGroup(tfBox);
                    tgBox.addChild(box);

                    vector[y] = new Sorting.Number(Main.vetorNumeros[y].numero, tgBox);
                    
                    bGroup.addChild(tgBox);
                    Main.su.addBranchGraph(bGroup);
                
                    }
                    
                    //===========Passar numeros!! ==========
                    for (int i = 0; i < Main.vectorCapacity; i++) {
                        Main.removeElements(Main.vetorNumeros);
                        Main.destroyVectorObject(Main.vectorShadowList, i);
                    }
                
                
                Main.vectorCapacity = Main.vectorCapacity * 2;
                Main.highlightsText("      vetor = novo vetor[vetor_capacidade * 2];", Main.textoVectorAdd);
                Main.vetorNumeros = new Sorting.Number[Main.vectorCapacity];

                Main.highlightsText("        para (int i = 0; i < vetor_capacidade / 2; i++) {", Main.textoVectorAdd);
                
                for (int i = 0; i < Main.vectorCapacity; i++) {

                    BranchGroup bGroup = new BranchGroup();

                    Box box = new Box(Main.raio, Main.raio, Main.raio, Main.criarAppCustom());
                    box.setCapability(Box.ENABLE_APPEARANCE_MODIFY);
                    Transform3D tfBox = new Transform3D();
                    checkElementPosition(i);

                    tfBox.setTranslation(new Vector3f(elementPosition.x, 0.0f, -0.25f));
                    TransformGroup tgBox = new TransformGroup(tfBox);
                    tgBox.addChild(box);

                    Main.vectorShadowList.add(new Sorting.Number(-1, tgBox));

                    bGroup.addChild(tgBox);
                    Main.su.addBranchGraph(bGroup);

                }
                
                
                
                for (int i = 0; i < Main.vectorCapacity / 2; i++) {
                    
                    
                    Main.highlightsText("          vetor[i] = vetorTemp[i];", Main.textoVectorAdd);
                    Main.vetorNumeros[i] = number[i];
                    
                    
                }
                
                for (int i = 0; i < Main.vectorCapacity / 2; i++) {
                    BranchGroup branchGroup = new BranchGroup();

                    Sphere sphere = new Sphere(Main.raio, Main.criarAppCustom());
                    sphere.setCapability(Sphere.ENABLE_APPEARANCE_MODIFY);
                    Transform3D tfSphere = new Transform3D();
                    checkElementPosition(i);
                    tfSphere.setTranslation(new Vector3f(elementPosition.x, elementPosition.y, elementPosition.z)); //z - 0.05f
                    TransformGroup tgSphere = new TransformGroup(tfSphere);
                    tgSphere.addChild(sphere);
                    branchGroup.addChild(tgSphere);
                    Main.vetorNumeros[i] = new Sorting.Number(vector[i].numero, tgSphere);
                    Main.su.addBranchGraph(branchGroup);
                    
                    try {
                        sleep(60);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(VectorThread.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                
                
                
                
                
                for (int i = 0; i < Main.vectorCapacity / 2; i++) {
                    Main.destroySphereGeneric(vector, i);
                    Main.destroyVectorObject(shadow, i);
                }
                
                //  --------------------ATÉ AQUI! ---------------------
                
                moveViewZ(0.8f);

            }

            String numberString = "";
            int number = -1;

            while (number < 0 || number > 9) {
                numberString = JOptionPane.showInputDialog("Qual o número à ser adicionado?");

                if (numberString == null || numberString.equals("")) {
                } else {
                    number = Integer.parseInt(numberString);
                }

            }

            System.out.println("Vai adicionar o: " + number);
            
            Main.highlightsText("    para (int i = tamanho_vetor; i > indice; i--) {", Main.textoVectorAdd);
            for (int i = Main.vectorSize; i > indexNumber; i--) {
                Main.highlightsText("      vetor[i] = vetor[i - 1];", Main.textoVectorAdd);
                Main.vetorNumeros[i] = Main.vetorNumeros[i - 1];
                Main.moveVectorObjectRight(Main.vetorNumeros, i, (i * 0.25f) - 0.4f);

            }

            BranchGroup branchGroup = new BranchGroup();

            Sphere sphere = new Sphere(Main.raio, Main.criarAppCustom());
            sphere.setCapability(Sphere.ENABLE_APPEARANCE_MODIFY);
            Transform3D tfSphere = new Transform3D();
            checkElementPosition(indexNumber);
            tfSphere.setTranslation(new Vector3f(elementPosition.x, elementPosition.y, elementPosition.z)); //z - 0.05f
            TransformGroup tgSphere = new TransformGroup(tfSphere);
            tgSphere.addChild(sphere);
            branchGroup.addChild(tgSphere);

            Main.highlightsText("    vetor[indice] = numero;", Main.textoVectorAdd);
            Main.vetorNumeros[indexNumber] = new Sorting.Number(number, tgSphere);
            Main.su.addBranchGraph(branchGroup);
            Main.highlightsText("    tamanho_vetor++;", Main.textoVectorAdd);
            Main.vectorSize++;
            Main.textPane.getStyledDocument().setCharacterAttributes(0, Main.textoVectorAdd.length(), Main.defaultText, true);
            Main.textPane2.setText("tamanho = " + Main.vectorSize + "\ncapacidade = " + Main.vectorCapacity);
        }

    }

    public static void popElement() {
        Main.textPane.setText(Main.textoVectorRemove);

        String indexString = "";
        int indexNumber = -1;

        while (indexNumber < 0 || indexNumber > 9) {
            indexString = JOptionPane.showInputDialog("Qual a posição do número à ser removido? Capacidade atual: " + Main.vectorCapacity);

            if (indexString == null || indexString.equals("")) {
            } else {
                indexNumber = Integer.parseInt(indexString);
            }

        }

        Main.highlightsText("  se (indice < 0 || indice >= tamanho_vetor) {\n", Main.textoVectorRemove);
        if (indexNumber < 0 || indexNumber >= Main.vectorSize) {
            Main.highlightsText("    Erro: O índice não está nos limites do vetor!\n", Main.textoVectorRemove);
            JOptionPane.showMessageDialog(null, "O índice não está dentro dos limites do vetor atual.");
            Main.textPane.getStyledDocument().setCharacterAttributes(0, Main.textoVectorAdd.length(), Main.defaultText, true);
            

        } else {
            
            Main.highlightsText("  } senao {\n", Main.textoVectorRemove);
            
            Main.highlightsText("    vetor[indice] = null;\n", Main.textoVectorRemove);
            Main.destroySphereGeneric(Main.vetorNumeros, indexNumber);

            Main.highlightsText("    para(int i = indice; i < tamanho_vetor; i++) {\n", Main.textoVectorRemove);
            for (int i = indexNumber; i < Main.vectorSize; i++) {
                Main.highlightsText("      se (i != tamanho_vetor) {\n", Main.textoVectorRemove);
                if (i != Main.vectorSize) {
                    Main.moveVectorObjectLeft(Main.vetorNumeros, i, (((i - 1) * 0.25f) - (0.4f)) + 0.02f);
                    Main.highlightsText("        vetor[i] = vetor[i + 1];\n", Main.textoVectorRemove);
                    Main.vetorNumeros[i] = Main.vetorNumeros[i + 1];
                }

            }
            Main.highlightsText("    tamanho_vetor--;", Main.textoVectorRemove);
            Main.vectorSize--;
            Main.textPane.getStyledDocument().setCharacterAttributes(0, Main.textoVectorAdd.length(), Main.defaultText, true);
            Main.textPane2.setText("tamanho = " + Main.vectorSize + "\ncapacidade = " + Main.vectorCapacity);
        }

    }
    
    public static void moveViewZ(float i) {
        
        Transform3D tf = new Transform3D();
        
        Main.su.getViewingPlatform().getViewPlatformTransform().getTransform(tf);
        
        tf.get(view);
        
        view.z += i;
        view.x += 0.01f;
        
        tf.set(view);
        Main.su.getViewingPlatform().getViewPlatformTransform().setTransform(tf);
        
        
    }

    public static void topElement() {

        if (Main.numberList.isEmpty()) {

            JOptionPane.showMessageDialog(null, "Não há elementos na fila.");

        } else {

            JOptionPane.showMessageDialog(null, "O elemento do topo da fila é: " + Main.numberList.get(0).getNumber());

        }
    }

    public static void showElements() {

        if (Main.vectorSize == 0 || Main.vetorNumeros.length == 0) {

            JOptionPane.showMessageDialog(null, "Não há elementos no vetor.");

        } else {


            String numeros = "{ ";

            for (int i = 0; i < Main.vectorSize; i++) {
                numeros += Main.vetorNumeros[i].getNumber() + " ";
            }
            numeros += "}";

            JOptionPane.showMessageDialog(null, "Elementos: " + numeros);

        }

    }

    public void callVectorButtons() {


        JFrame frame = new JFrame("Vector Actions");

        JPanel vectorButtonsPanel = new JPanel(new GridLayout(2, 0));

        JButton addButton = new JButton("Inserir");
        JButton removeButton = new JButton("Retirar");
        JButton lastElementButton = new JButton("Último Índice");
        JButton showElementsButton = new JButton("Vector Elements");

        addButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {      
                Thread t = new ThreadAuxiliary(vectorThread, 1);
                t.start();
            }
        });

        removeButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                Thread t = new ThreadAuxiliary(vectorThread, 2);
                t.start();
            }
        });

        lastElementButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                Thread t = new ThreadAuxiliary(vectorThread, 3);
                t.start();
            }
        });

        showElementsButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
//                showElements();
                moveViewZ(0.8f);
                
            }
        });

        JLabel exitLabel = new JLabel("Para finalizar a execução do vetor, feche esta janela");
        JTextArea exitText = new JTextArea("Para finalizar a execução do vetor, feche esta janela");
        exitText.setEditable(false);
        exitText.setLineWrap(true);
        exitText.setAutoscrolls(true);
        vectorButtonsPanel.add(addButton);
        vectorButtonsPanel.add(removeButton);
//        vectorButtonsPanel.add(lastElementButton);
//        vectorButtonsPanel.add(showElementsButton);
        frame.add(vectorButtonsPanel);
        frame.setBounds(415, 60, 300, 140);

        frame.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {

                for (int i = 0; i < Main.vectorSize; i++) {
                    Main.destroySphereGeneric(Main.vetorNumeros, i);
                }

                for (int i = 0; i < Main.vectorShadowList.size(); i++) {
                    Main.destroyVectorObject(Main.vectorShadowList, i);

                }

                Main.vectorSize = 0;
                Main.isRunning = false;
                Main.clearTexts();
                Main.frame.setEnabled(true);

            }
        });

        frame.setResizable(false);
        frame.setVisible(true);
        Main.textPane2.setText("tamanho = " + Main.vectorSize + "\ncapacidade = " + Main.vectorCapacity);
    }
}
